package com.hemerasolutions.v2trainer.dao;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.stereotype.Repository;

import com.hemerasolutions.v2trainer.dao.interfaces.LibraryDaoInterface;
import com.hemerasolutions.v2trainer.model.exercise.Equipment;
import com.hemerasolutions.v2trainer.model.exercise.Exercise;
import com.hemerasolutions.v2trainer.model.exerciseGroup.ExerciseGroup;
import com.hemerasolutions.v2trainer.model.library.Library;
import com.hemerasolutions.v2trainer.model.library.Library_;
import com.hemerasolutions.v2trainer.model.modality.Modality;
import com.hemerasolutions.v2trainer.model.modality.Modality_;
import com.hemerasolutions.v2trainer.model.training.Training;
import com.hemerasolutions.v2trainer.model.users.User;
import com.hemerasolutions.v2trainer.model.users.User_;

@Repository(value = "libraryDao")
public class LibraryDao extends BaseDao<Library> implements LibraryDaoInterface{
	private static final long serialVersionUID = 1L;

	
	@Override
	public List<Equipment> searchEquipmentsOfLibrary(Map<String, Object> fields) {
		
		List<Predicate> predicateList = new ArrayList<Predicate>();

		CriteriaBuilder cb = this.getEntityManager().getCriteriaBuilder();

		CriteriaQuery<Equipment> cq  = cb.createQuery(Equipment.class);
		
		Root<Equipment> equipment = cq.from(Equipment.class);

		Predicate pred;

		Join<Library,Equipment> junction = equipment.join("equipments",JoinType.LEFT); 

		
	    for (Map.Entry<String,Object> line : fields.entrySet()) {
	    	
	    	if( line.getKey().toString() == "name" 	 ||
		   		line.getKey().toString() == "description" ){
	    		
	    		pred = cb.like(cb.upper(equipment.<String>get(line.getKey().toString())), 
	    								"%"+line.getValue().toString().toUpperCase()+"%");
	            predicateList.add(pred);    		
	    	}

	    	if( line.getKey().toString() == "library"){
        		pred = cb.equal(cb.upper(junction.<String>get(line.getKey().toString())),line.getValue());
                predicateList.add(pred);    		
        	}	    	
	    	
	    	
	    	if( line.getKey().toString() == "begCreatedAt" ){ 
	    		pred = cb.greaterThanOrEqualTo(equipment.<Date>get("createdAt"), (Date)line.getValue());
	    		predicateList.add(pred);    		
	    	}
	    	
	    	if( line.getKey().toString() == "endCreatedAt" ){ 
	    		pred = cb.lessThanOrEqualTo(equipment.<Date>get("createdAt"), this.endDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		
	    	}
	    	
	    	if( line.getKey().toString() == "begChangedAt" ){ 
	    		pred = cb.greaterThanOrEqualTo(equipment.<Date>get("lastChange"), (Date)line.getValue());
	    		predicateList.add(pred);    		
	    	}

	    	if( line.getKey().toString() == "endChangedAt" ){ 
	    		pred = cb.lessThanOrEqualTo(equipment.<Date>get("lastChange"), this.endDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		
	    	}
			
	    }
	    
	    Predicate[] predicates = new Predicate[predicateList.size()];
	    predicateList.toArray(predicates);
	    cq.where(predicates);
	 
	    
	    return super.getEntityManager().createQuery(cq).getResultList();			
	
	
	}
	
	
	@Override
	public List<Modality> searchModalitysOfLibrary(Map<String,Object> fields) {

		
		List<Predicate> predicateList = new ArrayList<Predicate>();

		CriteriaBuilder cb = this.getEntityManager().getCriteriaBuilder();

		CriteriaQuery<Modality> cq  = cb.createQuery(Modality.class);

		Root<Library> library = cq.from(Library.class);

		Join<Library,Modality> libMod = library.join("modalitys"); 
		

		Predicate pred;

		
	    for (Map.Entry<String,Object> line : fields.entrySet()) {
	    	
	    	if( line.getKey().toString() == "name" 	 ||
		   		line.getKey().toString() == "description" ){
	    		
	    		pred = cb.like(cb.upper(libMod.<String>get(line.getKey().toString())), 
	    								"%"+line.getValue().toString().toUpperCase()+"%");
	            predicateList.add(pred);    		
	    	}

	    	if(line.getKey().toString() == "trainingType" ){

	    		pred = cb.equal(libMod.get(Modality_.trainingType), line.getValue());
	    		predicateList.add(pred);    		
	    		
	    	}
	    	
	    	
	    	if( line.getKey().toString() == "library"){
        		pred = cb.equal(library.get(Library_.id) ,((Library)line.getValue()).getId());
                predicateList.add(pred);    		
        	}	    	
	    	
	    	
	    	if( line.getKey().toString() == "begCreatedAt" ){ 
	    		pred = cb.greaterThanOrEqualTo(libMod.<Date>get("createdAt"), (Date)line.getValue());
	    		predicateList.add(pred);    		
	    	}
	    	
	    	if( line.getKey().toString() == "endCreatedAt" ){ 
	    		pred = cb.lessThanOrEqualTo(libMod.<Date>get("createdAt"), this.endDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		
	    	}
	    	
	    	if( line.getKey().toString() == "begChangedAt" ){ 
	    		pred = cb.greaterThanOrEqualTo(libMod.<Date>get("lastChange"), (Date)line.getValue());
	    		predicateList.add(pred);    		
	    	}

	    	if( line.getKey().toString() == "endChangedAt" ){ 
	    		pred = cb.lessThanOrEqualTo(libMod.<Date>get("lastChange"), this.endDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		
	    	}
			
	    }
	    
	    Predicate[] predicates = new Predicate[predicateList.size()];
	    predicateList.toArray(predicates);

	    cq.select(libMod);
	    cq.where(predicates);

	    return super.getEntityManager().createQuery(cq).getResultList();			
	}


	@Override
	public List<Exercise> searchExercisesOfLibrary(Map<String, Object> fields) {
		// TODO Auto-generated method stub
		return null;
	}



	@Override
	public List<Training> searchTrainingsOfLibrary(Map<String, Object> fields) {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public List<ExerciseGroup> searchExerciseGroupsOfLibrary(
			Map<String, Object> fields) {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public List<Library> listPublicAdminLibrarys(int userType) {
		

		CriteriaBuilder cb = this.getEntityManager().getCriteriaBuilder();

		CriteriaQuery<Library> cq  = cb.createQuery(Library.class);

		Root<User> user = cq.from(User.class);

		Join<User,Library> userLib = user.join("librarys"); 
		
		List<Predicate> predicateList = new ArrayList<Predicate>();
		
		Predicate pred;

		pred = cb.equal(user.get(User_.userType), User.USERTYPE_ADMIN);
		predicateList.add(pred);
		
		pred = cb.equal(userLib.get(Library_.shareType), Library.SHARE_TYPE_PUBLIC);
		predicateList.add(pred);
		
		cq.select(userLib);	
		cq.where(pred);

	    return super.getEntityManager().createQuery(cq).getResultList();				
		


	}


	@Override
	public List<Library> listPublicLibrarys() {

		CriteriaBuilder cb = this.getEntityManager().getCriteriaBuilder();

		CriteriaQuery<Library> cq  = cb.createQuery(Library.class);

		Root<Library> library = cq.from(Library.class);
		
		List<Predicate> predicateList = new ArrayList<Predicate>();
		
		Predicate pred;

		pred = cb.equal(library.get(Library_.shareType),Library.SHARE_TYPE_PUBLIC);
		predicateList.add(pred);
		
		cq.select(library);	
		cq.where(pred);

	    return super.getEntityManager().createQuery(cq).getResultList();			
	}


	@Override
	public List<Training> searchTrainingSystemsOfLibrary(
			Map<String, Object> fields) {
		// TODO Auto-generated method stub
		return null;
	}
}
